package com.firmiana.jt809.util;

import com.firmiana.jt809.config.GlobalConfig;
import com.firmiana.jt809.entity.ParameterModel;

/**
 * 函数工具类
 *
 * @author hucl
 * @date 2020/8/25 11:12
 */
public class FunctionUtils {

    public static String getHeaderAndFlag(long counter, String body, int dataType, long centerId, boolean isEncrypt) {
        if (body == null) {
            body = "";
        }
        ParameterModel pm = GlobalConfig.parModel;
        String header = "5B";
        String ver = Tools.turnDataLength(pm.getProtocolVer(), 6); //版本号
        String encryptFlag = "00";
        String encryptKey = "00000000";
        String endFlag = "5D";
        int length = body.length() / 2; // 字节长度
        // +26的原因：length为数据体的长度，需要 + 头标识(1字节) + 数据头(22字节) + CRC校验位(2字节) + 尾标识(1字节) = 26字节
        // 拼装成总数据包
        long dateLength = length + 26;
        if (isEncrypt) {
            encryptFlag = "01"; //加密标志位
            body = FunctionUtils.encrypt(pm.getEncryptKey(), body);
            encryptKey = Tools.toHexString(pm.getEncryptKey(), 4);
        }
        // 消息体
        String message = Tools.toHexString(dateLength, 4) + Tools.toHexString(counter, 4)
                + Tools.toHexString(dataType, 2) + Tools.toHexString(centerId, 4) + ver
                + encryptFlag + encryptKey + body;
        message = message + Tools.getCRCString(message);
        message = Tools.encoderStringEscape(message);
        message = header + message + endFlag;
        return message;
    }

    public static String encrypt(long key, String str) {
        int m1 = (int) GlobalConfig.parModel.getSecretKeyM();
        int a1 = (int) GlobalConfig.parModel.getSecretKeyA();
        int c1 = (int) GlobalConfig.parModel.getSecretKeyC();
        byte[] b = Tools.hexString2Bytes(str);
        int size = b.length;
        if (key == 0)
            key = 1;
        int i = 0;
        while (i < size) {
            key = (a1 * (key % m1) + c1) & Tools.MAX;
            short d = (short) ((key >> 20) & 0xFF);
            b[i++] ^= d;
//            byte v = b[i-1];
        }
        return Tools.toHexString(b);
    }

    /**
     * 转义
     *
     * @param packet 包数据
     * @return
     */
    public static String decoderStringEscape(byte[] packet) {
        StringBuilder sb = new StringBuilder();
        sb.append(Tools.toHexString(packet[0]));
        for (int i = 1; i < packet.length - 1; i++) {
            switch (packet[i]) {
                case 0x5A:
                    if (packet[i + 1] == 0x02) {
                        sb.append("5A");
                        i++;
                    } else if (packet[i + 1] == 0x01) {
                        sb.append("5B");
                        i++;
                    }
                    break;
                case 0x5E:
                    if (packet[i + 1] == 0x01) {
                        sb.append("5D");
                        i++;
                    } else if (packet[i + 1] == 0x02) {
                        sb.append("5E");
                        i++;
                    }
                    break;
                default:
                    sb.append(Tools.toHexString(packet[i]));
                    break;
            }
        }
        sb.append(Tools.toHexString(packet[packet.length - 1]));
        return sb.toString().toUpperCase();
    }


}
